package com.googlecode.connectlet.util;

import java.util.concurrent.ConcurrentLinkedQueue;

public abstract class Pool<T> {
	protected abstract T makeObject();
	/** @param obj */
	protected boolean activateObject(T obj) {
		return true;
	}
	/** @param obj */
	protected boolean passivateObject(T obj) {
		return true;
	}
	/** @param obj */
	protected void destroyObject(T obj) {/**/}

	private ConcurrentLinkedQueue<T> queue = new ConcurrentLinkedQueue<T>();

	public T borrowObject() {
		T obj;
		while ((obj = queue.poll()) != null) {
			if (activateObject(obj)) {
				return obj;
			}
			destroyObject(obj);
		}
		if ((obj = makeObject()) == null) {
			return null;
		}
		if (activateObject(obj)) {
			return obj;
		}
		destroyObject(obj);
		return null;
	}

	public void returnObject(T obj) {
		if (passivateObject(obj)) {
			queue.add(obj);
		} else {
			destroyObject(obj);
		}
	}

	public void addObject() {
		T obj = makeObject();
		if (obj != null) {
			queue.add(obj);
		}
	}

	public void removeObject() {
		T obj = queue.poll();
		if (obj != null) {
			destroyObject(obj);
		}
	}

	public void invalidateObject(T obj) {
		passivateObject(obj);
		destroyObject(obj);
	}

	public void clear() {
		T obj = queue.poll();
		while (obj != null) {
			destroyObject(obj);
			obj = queue.poll();
		}
	}

	public int getNumIdle() {
		return queue.size();
	}
}